home *** CD-ROM | disk | FTP | other *** search
- /* world.c
- * Copyright (1993)
- *
- * Jeff Elman. University of California, San Diego
- * Rik Belew. University of California, San Diego
- * Stefano Nolfi. Institute of Psychology, Rome.
- * Filippo Menczer. University of California, San Diego
- * Greg Linden. University of California, San Diego
- *
- * This software may be redistributed without charge;
- * this notice should be preserved.
- */
-
- #include "defs.h"
-
-
-
-
-
- /*
- * called in populati.c;
- * the world is updated to insert the organism in its cell
- */
- ins_org(ip)
-
- struct indiv *ip;
- {
- cell *temp;
-
- temp = (cell *)malloc(sizeof(cell));
- if (temp == (cell *) NIL_POINTER)
- {
- fprintf(stderr, "cell malloc error in ins_org()\n");
- exit(-1);
- }
- temp->type = org;
- temp->datum.ap = ip;
- temp->next = world[ip->worldx][ip->worldy];
- world[ip->worldx][ip->worldy] = temp;
-
- ins_org_Interactive(ip);
- }
-
-
-
- /*
- * the world is updated to insert a food element in a cell
- */
- boolean ins_food(element, x, y, check)
-
- int element;
- int x, y;
- boolean check;
- {
- cell *temp, *temp1;
-
- temp = temp1 = world[x][y];
- while (temp != (cell *)NIL_POINTER) {
- if (check)
- if (temp->type==food)
- if (react_table[temp->datum.atom][element].possible)
- return(FALSE);
- temp1 = temp;
- temp = temp->next;
- }
-
- temp = (cell *)malloc(sizeof(cell));
- if (temp == (cell *) NIL_POINTER)
- {
- fprintf(stderr, "cell malloc error in ins_food()\n");
- exit(-1);
- }
- temp->type = food;
- temp->datum.atom = element;
- temp->next = (cell *)NIL_POINTER;
- if (temp1 == (cell *)NIL_POINTER) world[x][y] = temp;
- else temp1->next = temp;
-
- return(TRUE);
- }
-
- /*
- * called in populati.c;
- * the world is updated to delete the organism from its cell
- */
- del_org(ip)
-
- struct indiv *ip;
- {
- cell *temp, *temp2;
- boolean done = FALSE;
- int itemNum=0;
- int x,y;
-
- x = ip->worldx;
- y = ip->worldy;
-
- temp = world[ip->worldx][ip->worldy];
- if (temp == (cell *)NIL_POINTER)
- {
- printf("ERROR: can't find indiv to be deleted");
- exit(1);
- }
- else if ((temp->type == org) && (temp->datum.ap == ip))
- {
- world[ip->worldx][ip->worldy] = temp->next;
- free((char *) temp);
- done = TRUE;
- }
- else while ((temp->next != (cell *)NIL_POINTER) &&
- !((temp->next->type == org) &&
- (temp->next->datum.ap == ip))) {
- temp = temp->next;
- itemNum++;
- }
- if (!done)
- {
- if (temp->next == (cell *)NIL_POINTER)
- {
- printf("ERROR: can't find indiv to be deleted");
- exit(1);
- }
- else
- {
- temp2 = temp->next;
- temp->next = temp2->next;
- free((char *) temp2);
- }
- }
-
-
- del_org_Interactive(x,y, itemNum);
- }
-
-
-
-
- /*
- * called in populati.c;
- * the world is filled with food elements of
- * the various types according to their distribution
- */
- init_world()
-
- {
- register int x,y,i;
- int t;
-
- /*
- * initialize world cells
- */
- for (x=0; x<x_dim; x++)
- for (y=0; y<y_dim; y++)
- world[x][y] = (cell *)NIL_POINTER;
-
- /*
- * fill in cells with food elements
- */
- t = abundance * x_dim * y_dim;
- for (i=0; i<t; i++) update_world();
- }
-
-
-
- /*
- * called in populati.c;
- * the world is replenished with new food elements
- * to make up for the ones that have been consumed
- */
- update_world()
-
- {
- int t,i;
- int xpos, ypos;
- int counter;
-
-
- for (t=0; t<types; t++)
- if (0.5 + rans(0.5) < (float)distrib[t][4]/100.0)
- {
-
- /* Don't allow two reactable atoms in the
- same cell. */
-
- counter=0;
-
- do
- {
- if (counter>100)
- {
- if(saturation) break;
- else
- {
- printf("Unable to place food \n(use the -S option to avoid trying to replenish a saturated world).\n");
- exit(1);
- }
- }
-
- xpos = 0;
- ypos = 0;
- for (i=0; i<distrib[t][2]; i++)
- xpos += (mrand(x_dim)-(int)(x_dim/2));
- for (i=0; i<distrib[t][3]; i++)
- ypos += (mrand(y_dim)-(int)(y_dim/2));
- xpos /= distrib[t][2];
- ypos /= distrib[t][3];
- xpos += (x_dim+distrib[t][0]);
- ypos += (y_dim+distrib[t][1]);
- xpos %= x_dim;
- ypos %= y_dim;
- counter++;
- } while (!(ins_food(t, xpos, ypos, TRUE)));
-
- update_world_Interactive(xpos, ypos);
- }
- }
-
-
-
-
- /* After digestion, the organism can only
- retain gutSize number of atoms inside it.
- Extra must be removed. */
-
- int expel (organism)
- struct indiv *organism;
- {
- int atoms_in_gut=0, counter, numExpelled = 0;
-
- for (counter=0; counter<types;counter++)
- atoms_in_gut+=organism->gut[counter];
-
- while (atoms_in_gut>organism->gutsize) {
- counter = mrand(types);
- if (organism->gut[counter]>0) {
- organism->gut[counter]--;
- ins_food(counter, organism->worldx, organism->worldy, FALSE);
- atoms_in_gut--;
- numExpelled++;
- }
- }
-
- return(numExpelled);
- }
-
-
- /*
- * u_digest() takes care of easy case when reactions
- * are unary (-U option) rather than binary:
- * all atomes reactive, no by-products...
- */
- void u_digest (organism)
- struct indiv *organism;
- {
- int x;
- float calories = 0.0;
-
- for (x=0;x<types;x++)
- {
- calories += organism->gut[x] * react_table[x][0].energy;
- organism->gut[x] = 0;
- organism->energy += calories;
- }
- }
-
-
- /* digest() attemps to match the atoms in the
- gut to get a reaction. Any reaction can
- produce new atoms which are still in
- the gut and can produce secondary
- reactions. These reactions can cause
- energy to be both added and subtracted from
- the organism. */
-
- void digest (organism)
- struct indiv *organism;
- {
-
- int order[MAXTYPES], counter, x,y, swap;
- boolean react;
-
- do {
- react = FALSE;
-
- /* Randomly determine the order with which to check
- the reactions */
- for (counter=0;counter<types; counter++)
- order[counter] = counter;
- if (types>1) {
- for (counter = 0; counter<types*2; counter++)
- {
- if (mrand(2) == 1) {
- x = mrand(types);
- do {
- y = mrand(types);
- } while (y==x);
- swap = order [x];
- order[x] = order [y];
- order[y] = swap;
- }
- }
- }
-
- for (x=0;x<types;x++)
- if (organism->gut[order[x]]>0)
- for (y=0;y<=x;y++)
- if (organism->gut[order[y]]>0)
- if ((x!=y)||(organism->gut[order[x]]>1))
- react = reactAtoms(organism, order[x], order[y]);
- } while (react);
- }
-
-
- /* Used by digest().
- If the atoms x and y can react, react
- them, modify the energy of of the organism appropriately,
- remove the atoms from the gut vector, add the byproducts,
- and set react = TRUE */
-
- boolean
- reactAtoms (organism, x, y)
- struct indiv *organism;
- int x,y;
- {
- int counter;
-
-
- if (react_table[x][y].possible==FALSE)
- return(FALSE);
- else {
- organism->gut[x]--;
- organism->gut[y]--;
-
- for (counter=0; counter<types; counter++)
- organism->gut[counter] += react_table[x][y].by_prod[counter];
-
- organism->energy+=react_table[x][y].energy;
-
- return(TRUE);
- }
- }
-
-
-
-
-
- /*
- * called by act_in_world() in gworld.c;
- * all food-content of new cell position is put
- * in the gut (may exceed gut_size);
- * the world is updated (food removed)
- *
- * NOTE: for now, organisms cannot eat each other
- */
- ingest(ip)
-
- struct indiv *ip;
- {
- cell *t1, *t2;
- int numIngested=0;
-
- while (((t1 = world[ip->worldx][ip->worldy]) !=
- (cell *)NIL_POINTER) && (t1->type == food))
- {
- ++(ip->gut[t1->datum.atom]);
- numIngested++;
- world[ip->worldx][ip->worldy] = t1->next;
- free((char *) t1);
- }
- if ((t2 = t1) != (cell *)NIL_POINTER)
- if (t1->type == org)
- while (t1->next != (cell *)NIL_POINTER)
- {
- t1 = t1->next;
- if (t1->type == food)
- {
- ++(ip->gut[t1->datum.atom]);
- numIngested++;
- t2->next = t1->next;
- free((char *) t1);
- t1 = t2;
- }
-
- else if (t1->type == org)
- t2 = t1;
- else
- {
- printf("ERROR: unrecognized cell content\n");
- exit(1);
- }
- }
-
- return(numIngested);
- }
-
-
-
- /*
- * act_in_world() causes the organism to move
- * and ingest food; if reactions are unary, all atoms
- * are processes and there is no need to expel
- */
-
- float act_in_world (organism)
- struct indiv *organism;
- {
- int startX, startY, numExpelled=0;
- float delta_en = organism->energy;
-
- startX = organism->worldx;
- startY = organism->worldy;
-
- move(organism);
- if (learn == 2) sense_world(organism);
- ingest(organism);
- if (unary_reactions) u_digest(organism);
- else
- {
- digest(organism);
- numExpelled = expel(organism);
- }
-
- actInWorldInteractive(organism, numExpelled, startX, startY);
-
- delta_en = organism->energy - delta_en;
- return(delta_en);
-
- }
-
-
-
-